/***************************************************************************
*   Copyright (C) 2010-2011 by swkyer <swkyer@gmail.com>                  *
*                                                                         *
*   This program is free software; you can redistribute it and/or modify  *
*   it under the terms of the GNU General Public License as published by  *
*   the Free Software Foundation; either version 2 of the License, or     *
*   (at your option) any later version.                                   *
*                                                                         *
*   This program is distributed in the hope that it will be useful,       *
*   but WITHOUT ANY WARRANTY; without even the implied warranty of        *
*   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the         *
*   GNU General Public License for more details.                          *
*                                                                         *
*   You should have received a copy of the GNU General Public License     *
*   along with this program; if not, write to the                         *
*   Free Software Foundation, Inc.,                                       *
*   59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.             *
***************************************************************************/
#ifndef __MIPS32OPC_H__
#define __MIPS32OPC_H__

#include "Ejtag.h"


#define MIPS32_OPC_BEQ	0x04
#define MIPS32_OPC_BNE	0x05
#define MIPS32_OPC_ADDI	0x08
#define MIPS32_OPC_AND	0x24
#define MIPS32_OPC_COP0	0x10
#define MIPS32_OPC_JR	0x08
#define MIPS32_OPC_LUI	0x0F
#define MIPS32_OPC_LW	0x23
#define MIPS32_OPC_LBU	0x24
#define MIPS32_OPC_LHU	0x25
#define MIPS32_OPC_MFHI	0x10
#define MIPS32_OPC_MTHI	0x11
#define MIPS32_OPC_MFLO	0x12
#define MIPS32_OPC_MTLO	0x13
#define MIPS32_OPC_SB	0x28
#define MIPS32_OPC_SH	0x29
#define MIPS32_OPC_SW	0x2B
#define MIPS32_OPC_ORI	0x0D

#define MIPS32_COP0_MF	0x00
#define MIPS32_COP0_MT	0x04

#define MIPS32_R_INST(opcode, rs, rt, rd, shamt, funct)	\
		(((opcode) << 26) |((rs) << 21) | ((rt) << 16) | ((rd) << 11)| ((shamt) << 6) | (funct))
#define MIPS32_I_INST(opcode, rs, rt, immd)	\
		(((opcode) << 26) |((rs) << 21) | ((rt) << 16) | (immd))
#define MIPS32_J_INST(opcode, addr)	\
		(((opcode) << 26) |(addr))

#define MIPS32_NOP					0x00000000
#define MIPS32_ADDI(tar, src, val)	MIPS32_I_INST(MIPS32_OPC_ADDI, src, tar, val)
#define MIPS32_AND(reg, off, val)	MIPS32_R_INST(0, off, val, reg, 0, MIPS32_OPC_AND)
#define MIPS32_BEQ(src,tar,off)		MIPS32_I_INST(MIPS32_OPC_BEQ, src, tar, off)
#define MIPS32_BNE(src,tar,off)		MIPS32_I_INST(MIPS32_OPC_BNE, src, tar, off)
#define MIPS32_B(off)				MIPS32_BEQ(0, 0, off)
#define MIPS32_JR(reg)				MIPS32_R_INST(0, reg, 0, 0, 0, MIPS32_OPC_JR)
#define MIPS32_MFC0(gpr, cpr, sel)	MIPS32_R_INST(MIPS32_OPC_COP0, MIPS32_COP0_MF, gpr, cpr, 0, sel)
#define MIPS32_MTC0(gpr, cpr, sel)	MIPS32_R_INST(MIPS32_OPC_COP0, MIPS32_COP0_MT, gpr, cpr, 0, sel)
#define MIPS32_LBU(reg, off, base)	MIPS32_I_INST(MIPS32_OPC_LBU, base, reg, off)
#define MIPS32_LHU(reg, off, base)	MIPS32_I_INST(MIPS32_OPC_LHU, base, reg, off)
#define MIPS32_LUI(reg, val)		MIPS32_I_INST(MIPS32_OPC_LUI, 0, reg, val)
#define MIPS32_LW(reg, off, base)	MIPS32_I_INST(MIPS32_OPC_LW, base, reg, off)
#define MIPS32_MFLO(reg)			MIPS32_R_INST(0, 0, 0, reg, 0, MIPS32_OPC_MFLO)
#define MIPS32_MFHI(reg)			MIPS32_R_INST(0, 0, 0, reg, 0, MIPS32_OPC_MFHI)
#define MIPS32_MTLO(reg)			MIPS32_R_INST(0, reg, 0, 0, 0, MIPS32_OPC_MTLO)
#define MIPS32_MTHI(reg)			MIPS32_R_INST(0, reg, 0, 0, 0, MIPS32_OPC_MTHI)
#define MIPS32_ORI(src, tar, val)	MIPS32_I_INST(MIPS32_OPC_ORI, src, tar, val)
#define MIPS32_SB(reg, off, base)	MIPS32_I_INST(MIPS32_OPC_SB, base, reg, off)
#define MIPS32_SH(reg, off, base)	MIPS32_I_INST(MIPS32_OPC_SH, base, reg, off)
#define MIPS32_SW(reg, off, base)	MIPS32_I_INST(MIPS32_OPC_SW, base, reg, off)

/* ejtag specific instructions */
#define MIPS32_DRET					0x4200001F
#define MIPS32_SDBBP				0x7000003F


#define UPPER16(uint32_t) 			(uint32_t >> 16)
#define LOWER16(uint32_t) 			(uint32_t & 0xFFFF)
#define NEG16(v) 					(((~(v)) + 1) & 0xFFFF)


extern const ubase_t mips32_microcode_probe[];
extern const ubase_t mips32_microcode_dbgexceprtn[];

extern const ubase_t mips32_microcode_readregisters[];
extern const ubase_t mips32_microcode_writeregisters[];

extern const ubase_t mips32_microcode_readbyte[];
extern const ubase_t mips32_microcode_readhalf[];
extern const ubase_t mips32_microcode_readword[];
extern const ubase_t mips32_microcode_writebyte[];
extern const ubase_t mips32_microcode_writehalf[];
extern const ubase_t mips32_microcode_writeword[];

extern const ubase_t mips32_microcode_readdebug[];
extern const ubase_t mips32_microcode_writedebug[];
extern const ubase_t mips32_microcode_readdcr[];
extern const ubase_t mips32_microcode_writedcr[];

extern const ubase_t mips32_microcode_singlestepset[];
extern const ubase_t mips32_microcode_singlestepclear[];

extern const ubase_t mips32_microcode_readcp0[];
extern const ubase_t mips32_microcode_writecp0[];
//extern const ubase_t mips32_microcode_readdepc[];
extern const ubase_t mips32_microcode_writedepc[];
extern const ubase_t mips32_microcode_readbytes[];
extern const ubase_t mips32_microcode_writebytes[];
extern const ubase_t mips32_microcode_readhalfs[];
extern const ubase_t mips32_microcode_writehalfs[];
extern const ubase_t mips32_microcode_readwords[];
extern const ubase_t mips32_microcode_writewords[];

extern const ubase_t mips32_microcode_readibs[];
extern const ubase_t mips32_microcode_writeibs[];
extern const ubase_t mips32_microcode_readdbs[];
extern const ubase_t mips32_microcode_writedbs[];
extern const ubase_t mips32_microcode_writehwbkpt[];
extern const ubase_t mips32_microcode_writehwwpt[];

extern const ubase_t mips32_microcode_flushicache[];
extern const ubase_t mips32_microcode_flushdcache[];
extern const ubase_t mips32_microcode_flushicacherange[];
extern const ubase_t mips32_microcode_flushdcacherange[];
extern const ubase_t mips32_microcode_synci[];
extern const ubase_t mips32_microcode_readitag[];
extern const ubase_t mips32_microcode_readdtag[];
extern const ubase_t mips32_microcode_readtlb[];
extern const ubase_t mips32_microcode_writetlb[];

extern const ubase_t mips32_microcode_readcpx[];
extern const ubase_t mips32_microcode_writecpx[];


#endif /* end of __MIPS32OPC_H__ */
